package com.peanut.devlibrary.media;

import android.content.Context;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.SystemClock;

import com.peanut.devlibrary.util.StringUtil;
import com.tencent.mars.xlog.Log;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * before use you should set listener and file path
 */
public class VoiceRecorder {
    private static final String TAG = VoiceRecorder.class.getSimpleName();
    MediaRecorder recorder;

    static final String PREFIX = "voice";
    static final String EXTENSION = ".aac";

    private boolean isRecording = false;
    private long startTime;
    private String voiceFolderPath = null;
    private String voiceFileName = null;
    private File file;
    private Handler handler;

    public VoiceRecorder(Handler handler) {
        this.handler = handler;
    }

    /**
     * start recording to the file
     */
    public String startRecording(Context appContext) {
        file = null;
        try {
            // need to create recorder every time, otherwise, will got exception
            // from setOutputFile when try to reuse
            if (recorder != null) {
                recorder.release();
                recorder = null;
            }
            recorder = new MediaRecorder();
            recorder.setOnErrorListener(errorListener);
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            recorder.setAudioChannels(1); // MONO
            recorder.setAudioSamplingRate(8000); // 8000Hz
            recorder.setAudioEncodingBitRate(64); // seems if change this to
                                                    // 128, still got same file
                                                    // size.
            // one easy way is to use temp file
            // file = File.createTempFile(PREFIX + userId, EXTENSION,
            // User.getVoicePath());
            voiceFileName = PREFIX+"_"+System.currentTimeMillis() + EXTENSION;
            if(StringUtil.isNullOrEmpty(voiceFolderPath)){
                voiceFolderPath = getDefaultPath(appContext) + "/";
            }
            String resultFilePath = voiceFolderPath + voiceFileName;
            file = new File(resultFilePath);
            if(file.exists()){
                file.delete();
            }
            file.createNewFile();
            Log.e(TAG, "new file created "+file.getAbsolutePath());

            recorder.setOutputFile(file.getAbsolutePath());
            recorder.prepare();
            isRecording = true;
            recorder.start();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "prepare() failed "+e.toString());
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (isRecording) {
                        android.os.Message msg = new android.os.Message();
                        msg.what = recorder.getMaxAmplitude() * 13 / 0x7FFF;
                        handler.sendMessage(msg);
                        SystemClock.sleep(100);
                    }
                } catch (Exception e) {
                    // from the crash report website, found one NPE crash from
                    // one android 4.0.4 htc phone
                    // maybe handler is null for some reason
                    Log.e(TAG, e.toString());
                }
            }
        }).start();
        startTime = new Date().getTime();
        Log.d(TAG, "start voice recording to file:" + file.getAbsolutePath());
        return file == null ? null : file.getAbsolutePath();
    }

    public void setVoiceFolderPath(String path){
        this.voiceFolderPath = path;
    }

    /**
     * stop the recoding
     * 
     * @return seconds of the voice recorded
     */

    public void discardRecording() {
        if (recorder != null) {
            try {
                recorder.setOnErrorListener(null);
                recorder.setOnInfoListener(null);
                recorder.setPreviewDisplay(null);
                recorder.stop();
                recorder.release();
                recorder = null;
                if (file != null && file.exists() && !file.isDirectory()) {
                    file.delete();
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
                Log.e(TAG,"discardRecording IllegalStateException "+e.toString());
            } catch (RuntimeException e){
                e.printStackTrace();
                Log.e(TAG,"discardRecording RuntimeException "+e.toString());
            }
            isRecording = false;
        }
    }

    public int stopRecoding() {
        if(recorder != null){
            isRecording = false;
            recorder.setOnErrorListener(null);
            recorder.setOnInfoListener(null);
            recorder.setPreviewDisplay(null);
            recorder.stop();
            recorder.release();
            recorder = null;
            
            if(file == null || !file.exists() || !file.isFile()){
                return -1;
            }
            if (file.length() == 0) {
                file.delete();
                return -1;
            }
            int seconds = (int) (new Date().getTime() - startTime) / 1000;
            Log.d(TAG, "voice recording finished. seconds:" + seconds + " file length:" + file.length());
            return seconds;
        }
        return 0;
    }

    protected void finalize() throws Throwable {
        super.finalize();
        if (recorder != null) {
            recorder.release();
        }
    }

    public String getVoiceFileName() {
        return  voiceFileName;
    }

    public boolean isRecording() {
        return isRecording;
    }

    
    public String getVoiceFilePath() {
        return file.getAbsolutePath();
    }

    private String getDefaultPath(Context appContext){
        return  "/Android/data/" + appContext.getPackageName() + "/";
    }

    private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
        @Override
        public void onError(MediaRecorder mr, int what, int extra) {
            Log.d(TAG,"onError "+what+" "+extra);
        }
    };

    

}
